/*
 * Copyright (C) 2008 Andreas Pabst <info@timbap.de>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 2 for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <lo/lo.h>

#include "player.h"
#include "timecoder.h"

#define TIMBAP_ADDR_POSITION   "/timbap_position"
#define TIMBAP_ADDR_VELOCITY   "/timbap_velocity"
#define TIMBAP_ADDR_POWER      "/timbap_power"
#define TIMBAP_ADDR_FRACPLAYED "/played"


int timbap_loadfile_handler(const char *path, const char *types, lo_arg **argv, 
                            int argc, void *data, void *user_data)
{
    struct player_t *pl = user_data;
    fprintf(stderr, "timbap_loadfile_handler called\n");
    if(argc > 0) {
        if(strlen(&argv[0]->s) > 7) {
            pl->timbap_conn.fileuri = &argv[0]->s;
            pl->timbap_conn.load_rq = 1;
        } else 
            pl->timbap_conn.unload_rq = 1;
    }
    return 0;
}


void timbap_init_receiver(struct player_t *pl, int recv_port)
{
    pl->timbap_conn.load_rq = 0;
    pl->timbap_conn.unload_rq = 1;
    pl->timbap_conn.fileuri = NULL;

    char recv_port_str [10];
    snprintf (recv_port_str, (size_t)10, "%d", recv_port);

    fprintf(stderr, "Initializing OSC server on port %d...\n", recv_port);
    pl->timbap_conn.osc_server = lo_server_new(recv_port_str, NULL);
    lo_server_add_method(pl->timbap_conn.osc_server, "/loadfile", "s", 
                         timbap_loadfile_handler, pl);
}


void timbap_send_float(lo_address *osc_dest, char *osc_addrpattern, float val)
{
    if(lo_send(osc_dest, osc_addrpattern, "f", val) == -1) {
        fprintf(stderr,"timbap OSC error %d: %s\n", 
                lo_address_errno(osc_dest), lo_address_errstr(osc_dest));
    }
}


void timbap_publish_status(struct player_t *pl, struct timecoder_t *tc) 
{

    float tim_pwr = tc->signal_level / 10000;
    float tim_pos = (float)timecoder_get_position(tc, NULL);
    float tim_vel;
    
    timbap_send_float(pl->timbap_conn.osc_dest, TIMBAP_ADDR_POWER, tim_pwr);

    if(tim_pos != -1)
        timbap_send_float(pl->timbap_conn.osc_dest, TIMBAP_ADDR_POSITION, tim_pos);
    
    if(pl && pl->timecoder) {
        /* send played fraction and velocity from player only if connected */
        if (pl->track) {
            float tim_played = 0;
            if (pl->track->length > 0) {
                tim_played = (pl->position - pl->offset) / pl->track->length;
                if (tim_played > 1) tim_played = 1;
                if (tim_played < 0) tim_played = 0;
            }
            timbap_send_float(pl->timbap_conn.osc_dest, TIMBAP_ADDR_FRACPLAYED, 
                              tim_played);
        }
        tim_vel = pl->pitch;
    } else {
        int pitch_unavailable = timecoder_get_pitch(tc, &tim_vel);
        if(pitch_unavailable) 
            tim_vel = 0;
    }
    timbap_send_float(pl->timbap_conn.osc_dest, TIMBAP_ADDR_VELOCITY, tim_vel);
}


void timbap_init_sender(struct player_t *pl, int send_port)
{
    char send_port_string [10];
    snprintf (send_port_string, (size_t)10, "%d", send_port);
    
    pl->timbap_conn.osc_dest = lo_address_new(NULL, send_port_string);
}

